package com.xframe.xdal.core.listener;




import com.xframe.xdal.core.DataBaseAccess;
import com.xframe.xdal.core.listener.model.RowChangedEvent;
import com.xframe.xdal.core.manage.DBColumnInfo;
import com.xframe.xdal.core.manage.DBTableInfo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 监听器的抽象基类
 *
 * @author xufeng
 */
public abstract class DataBaseListener implements IDataBaseListener {


    protected Map<String, String> snapshot;
    protected Map<String, DBTableInfo> tables;
    protected DataBaseAccess dataBaseAccess;
    protected List<RowEventListener> listeners = new ArrayList<>();

    protected Long processID;
    protected String username;
    protected String password;
    protected String url;
    protected IFilters filters = null;

    public Long getProcessID() {
        return processID;
    }

    public void setProcessID(Long processID) {
        this.processID = processID;
    }

    public DataBaseListener(DataBaseAccess dataBaseAccess){
        this.snapshot = new HashMap<>();
        this.dataBaseAccess = dataBaseAccess;
        this.username = dataBaseAccess.getDataSource().getUsername();
        this.password = dataBaseAccess.getDataSource().getPassword();
        this.url = dataBaseAccess.getDataSource().getJdbcUrl();
    }

    @Override
    public void addFilters(IFilters filters) {
        this.filters = filters;
    }

    protected boolean filterTable(DBTableInfo dbTableInfo){
        if(dbTableInfo == null){
            return false;
        }
        if(this.filters != null){
            return this.filters.filterTable(dbTableInfo);
        }
        return true;
    }


    @Override
    public String getDbType(){
        return this.dataBaseAccess.getDataSource().getDataSourceTypeEnums().toString();
    }

    @Override
    public String getDbName(){
        return this.dataBaseAccess.getDataSource().getDatabaseName();
    }

    @Override
    public void addRowEventListener(RowEventListener rowEventListener) {
        this.listeners.add(rowEventListener);
    }








    protected void createMap(DBTableInfo dbTableInfo, List<Object> dataList,Map<String, Object> dataMap){
        List<DBColumnInfo> columnInfos = dbTableInfo.getDbColumnInfoList();
        for(int index = 0; index < columnInfos.size(); index++){
            if(index + 1  < dataList.size()){
                DBColumnInfo columnInfo = columnInfos.get(index);
                dataMap.put(columnInfo.getColumnName(),dataList.get(index + 1));
            }
        }
    }



    protected Map<String, Object> createMap(DBTableInfo dbTableInfo, Serializable[] dataList){
        Map<String, Object> dataMap = new HashMap<>();
        List<DBColumnInfo> columnInfos = dbTableInfo.getDbColumnInfoList();
        for(int index = 0; index < columnInfos.size(); index++){

            if(index < dataList.length){
                DBColumnInfo columnInfo = columnInfos.get(index);
                dataMap.put(columnInfo.getColumnName(),dataList[index]);
            }

        }
        return dataMap;
    }

    protected RowChangedEvent builderRowChangedEvent(DBTableInfo sourceTableInfo, String event, Map<String, Object> dataMap){
        return new RowChangedEvent(this.getDbName(),this.getDbType(),sourceTableInfo, event, dataMap,this.getProcessID());
    }


    @Override
    public abstract void start();
}
